class Feature(object):
	def __init__(self, name, code, dynamic=False):
		self.name = name
		self.code = code
		self.dynamic = dynamic
		
	def eval(self, env, state=None):
		if not state and self.dynamic:
			raise RuntimeError("Dynamic feature needs a state to eval in")
		if state:
			return eval(self.code, env, state)
		else:
			return eval(self.code, env)
		
	
	def ex(self, env, state=None):
		if not state and self.dynamic:
			raise RuntimeError("Dynamic feature needs a state to eval in")
		if not state:
			state = {}
		else:
			state = state.copy()
		exec ''.join([self.name,'=',self.code]) in env, state
		return state
	
class FeatureParser(object):
	def __init__(self, env):
		self.env = env
		self.staticFeatures = {}
		self.dynamicFeatures = {}
		
	def parse(self, code, start):
		mode = 0
		for i,line in enumerate(code):
			line = line.strip()
			if len(line) == 0:
					continue
			if line == "STATIC:":
				mode = 0
				continue
			elif line == "DYNAMIC:":
				mode = 1
				continue
			lineParts = [l.strip() for l in line.split('=')]
			if len(lineParts) != 2:
				raise RuntimeError("STRIPS (line " + str(start+i) + 
									"): Expected one assignment per line: "\
									+ line)
			varName, varVal = lineParts
			if varName in self.env or varName in self.dynamicFeatures \
					or varName in self.staticFeatures:
				raise RuntimeError("STRIPS (line " + str(start+i) + 
									"): Name collision: " + varName)
			if mode == 0:
				self.staticFeatures[varName] = Feature(varName, varVal)
			else:
				self.dynamicFeatures[varName] = Feature(varName, varVal, True)